package com.dm.service.impl;

import com.dm.common.Const;
import com.dm.common.enums.ResponseCode;
import com.dm.dao.FileDao;
import com.dm.dao.FolderDao;
import com.dm.dao.RecordDao;
import com.dm.dto.FileAttributeDto;
import com.dm.dto.FilesDto;
import com.dm.dto.ResponseDto;
import com.dm.dto.input.FileDto;
import com.dm.dto.input.FileSearchDto;
import com.dm.dto.input.UserDto;
import com.dm.entity.Record;
import com.dm.service.FileService;
import com.dm.utils.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author hqw521@qq.com
 * @date 2018/11/16 15:59
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class FileServiceImpl implements FileService {
    @Autowired
    private RecordDao recordDao;

    @Autowired
    private FileDao fileDao;

    @Autowired
    private FolderDao folderDao;

    @Override
    public ResponseDto createFile(FileDto fileDto) {
        ResponseDto responseDto = new ResponseDto();
        Map<String, String> map = FileUtil.createFile(fileDto.getFileType(), Const.uploadHost, Const.filePath);
        // 文件实际路径
        fileDto.setFilePath(map.get("realPath"));
        // 文件相对路径
        fileDto.setRelativePath(map.get("relativePath"));
        // 设置文件名
        fileDto.setFileName(fileDto.getFileName() + "." + fileDto.getFileType());
        Integer result = fileDao.insertFile(fileDto);
        if (result > 0) {
            responseDto.setMsg("文件创建成功");
            responseDto.setStatus(ResponseCode.SUCCESS.getCode());
            // 操作记录
            Record record = new Record();
            record.setUserId(fileDto.getUserId());
            record.setOperation("创建" + fileDto.getFileName() + "文件");
            recordDao.insertRecord(record);

            return responseDto;
        }

        responseDto.setMsg("文件创建失败");
        responseDto.setStatus(ResponseCode.ERROR.getCode());
        return responseDto;
    }

    @Override
    public ResponseDto<Map<String, String>> uploadFile(File file, String fileName, String fileContentType, String folderPath) {
        ResponseDto<Map<String, String>> responseDto = new ResponseDto<>();
        try {
            // 将File转为MultipartFile
            FileInputStream fileInputStream = new FileInputStream(file);
            MultipartFile multipartFile = new MockMultipartFile(fileName, fileName, fileContentType, fileInputStream);

            // 将文件上传到另一台服务器上
            Map<String, String> map = FileUtil.upload(multipartFile, Const.uploadHost, Const.filePath);
            responseDto.setData(map);
            return responseDto;
        } catch (Exception e) {
            e.printStackTrace();
            responseDto.setStatus(ResponseCode.ERROR.getCode());
            responseDto.setMsg("文件上传失败");
            return responseDto;
        }
    }

    @Override
    public ResponseDto addFile(FileDto fileDto) {
        ResponseDto responseDto = new ResponseDto();
        Integer result = fileDao.insertFile(fileDto);
        if (result > 0) {
            responseDto.setMsg("文件新增成功");
            responseDto.setStatus(ResponseCode.SUCCESS.getCode());
            // 操作记录
            Record record = new Record();
            record.setUserId(fileDto.getUserId());
            record.setOperation("上传" + fileDto.getFileName() + "文件");
            recordDao.insertRecord(record);

            return responseDto;
        }
        responseDto.setMsg("文件新增失败");
        responseDto.setStatus(ResponseCode.ERROR.getCode());
        return responseDto;
    }

    @Override
    public ResponseDto<List> findFiles(UserDto userDto) {
        ResponseDto<List> responseDto = new ResponseDto<>();

        List files = fileDao.findFiles(userDto);
        responseDto.setStatus(ResponseCode.SUCCESS.getCode());
        responseDto.setData(getFilesDto(files));
        return responseDto;
    }

    @Override
    public ResponseDto<List> findFilesByFolder(Integer userId, Integer folderId) {
        ResponseDto<List> responseDto = new ResponseDto<>();
        List foldersDtos = folderDao.findFoldersByParentFolder(folderId);

        List filesDtos = fileDao.findFilesByFolder(userId, folderId);
        foldersDtos.addAll(filesDtos);
        responseDto.setStatus(ResponseCode.SUCCESS.getCode());
        responseDto.setData(foldersDtos);

        return responseDto;
    }

    @Override
    public ResponseDto fileRename(FileDto fileDto) {
        ResponseDto responseDto = new ResponseDto();
        responseDto.setStatus(ResponseCode.ERROR.getCode());
        // 新文件和以前文件名不同时，才有必要进行重命名
        if (!fileDto.getOldFileName().equals(fileDto.getFileName())) {
            Integer result = fileDao.fileRename(fileDto.getFileName(), fileDto.getFileId());
            if (result > 0) {
                responseDto.setStatus(ResponseCode.SUCCESS.getCode());
                // 操作记录
                Record record = new Record();
                record.setUserId(fileDto.getUserId());
                record.setOperation("将" + fileDto.getOldFileName() + "文件重命名为" + fileDto.getFileName());
                recordDao.insertRecord(record);
                responseDto.setMsg("重命名成功");
            } else {
                responseDto.setMsg("重命名失败");
            }
            return responseDto;
        } else {
            responseDto.setMsg("新文件名和旧文件名相同");
            return responseDto;
        }
    }

    @Override
    public ResponseDto deleteFiles(Integer userId, String[] ids, String[] fileRelativePaths) {
        // 删除服务器中存储的文件
        for (String path : fileRelativePaths) {
            FileUtil.delete(Const.uploadHost + path);
        }
        // 获取要删除的文件名
        List<String> fileNames = findFileName(ids);
        // 删除数据库中文件信息
        Integer result = fileDao.deleteFiles(stringToInteger(ids));
        ResponseDto responseDto = new ResponseDto();
        if (result > 0) {
            // 添加删除记录
            Record record = new Record();
            record.setUserId(userId);
            for (String fileName : fileNames) {
                record.setOperation("删除" + fileName + "文件");
                recordDao.insertRecord(record);
            }
            responseDto.setStatus(ResponseCode.SUCCESS.getCode());
            responseDto.setMsg("删除成功");
        } else {
            responseDto.setStatus(ResponseCode.ERROR.getCode());
            responseDto.setMsg("删除失败");
        }
        return responseDto;
    }

    @Override
    public List<String> findFileName(String[] ids) {
        return fileDao.findFileName(stringToInteger(ids));
    }

    @Override
    public ResponseDto<List<FilesDto>> fileSearch(FileSearchDto fileSearchDto) {
        ResponseDto<List<FilesDto>> responseDto = new ResponseDto<>();
        List<FilesDto> filesDtos = fileDao.fileSearch(fileSearchDto);
        responseDto.setData(filesDtos);
        responseDto.setStatus(ResponseCode.SUCCESS.getCode());
        return responseDto;
    }

    @Override
    public ResponseDto<FileAttributeDto> findFileAttribute(Integer fileId) {
        ResponseDto<FileAttributeDto> responseDto = new ResponseDto<>();
        FileAttributeDto fileAttributeDto = fileDao.findFileAttribute(fileId);
        responseDto.setData(fileAttributeDto);
        responseDto.setStatus(ResponseCode.SUCCESS.getCode());
        return responseDto;
    }

    @Override
    public void updateClickNum(Integer fileId) {
        fileDao.updateClickNum(fileId);
    }

    @Override
    public InputStream downloadMultiFile(String[] ids) {
        List<FileDto> fileDtos = fileDao.findFileNameAndPath(stringToInteger(ids));
        return FileUtil.compressFileToZip(fileDtos);
    }

    private List<FilesDto> getFilesDto(List<com.dm.entity.File> files) {
        List<FilesDto> filesDtos = new ArrayList<>();
        String userName = "";
        if (files.size() > 0) {
            userName = files.get(0).getDmUserByUserId().getUserName();
        }
        for (com.dm.entity.File file : files) {
            FilesDto filesDto = new FilesDto();
            filesDto.setFileId(file.getFileId());
            filesDto.setFileName(file.getFileName());
            filesDto.setFileSize(file.getFileSize());
            filesDto.setRelativePath(file.getRelativePath());
            filesDto.setClickNumber(file.getClickNumber());
            filesDto.setUpdateMsg(file.getUpdateTime().toString() + " " + userName);
            filesDtos.add(filesDto);
        }
        return filesDtos;
    }

    /**
     * 将数字字符串转为整型
     *
     * @param strs 文件ID
     * @return 整数型文件ID
     */
    private Integer[] stringToInteger(String[] strs) {
        Integer[] ints = new Integer[strs.length];
        for (int i = 0; i < strs.length; i++) {
            ints[i] = Integer.valueOf(strs[i]);
        }
        return ints;
    }
}
